﻿; 安装程序初始定义常量 
!define PRODUCT_NAME "美剧精灵"
!define PRODUCT_OUTDIR "${ProcOutDir}"
!define PRODUCT_VERSION "${Version}"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" 
!define PRODUCT_UNINST_ROOT_KEY "HKLM" 
!define PRODUCT_INST_VALUE_KEY "Software\IBoFang" 

!define PROCESS_NAME "spirit.exe" 

; 设置覆盖标记 
SetOverwrite on 
; 设置压缩选项 
SetCompress auto 
; 选择压缩方式 
SetCompressor /SOLID lzma 
; 设置数据块优化 
SetDatablockOptimize on 

;安装类型 
;InstType "完全安装" 
;InstType "推荐安装" 
;InstType "精简安装" 

; ------ MUI 现代界面定义 (1.67 版本以上兼容) ------ 
;!include "MUI.nsh" 
;!include "Sections.nsh" 

; MUI 预定义常量 

;只有单击"取消"才能取消安装 
!define MUI_ABORTWARNING 

;安装程序的安装图标和卸载图标 
!define MUI_ICON ".\res\install.ico" 
!define MUI_UNICON ".\res\uninstall.ico" 

;欢迎页面左边的图片 
!define MUI_WELCOMEFINISHPAGE_BITMAP ".\res\welcome.bmp" 

;下面三行定义上面图片在右边显示以有图片的路径 
!define MUI_HEADERIMAGE 
!define MUI_HEADERIMAGE_RIGHT 
!define MUI_HEADERIMAGE_BITMAP ".\res\logo.bmp" 

;区段描述在下方显示。 
!define MUI_COMPONENTSPAGE_SMALLDESC 

;自已定义软件的标题 
!define MUI_WELCOMEPAGE_TITLE "美剧精灵"

!include ".\NSIS\unicode\Include\MUI.nsh"

;渠道号
Var SpiritChannel
;安装包文件名
Var InstFileName
;peerID
Var PeerID

;欢迎页面 
!insertmacro MUI_PAGE_WELCOME 

;组件选择页面 
!insertmacro MUI_PAGE_COMPONENTS 
; 安装目录选择页面 
!insertmacro MUI_PAGE_DIRECTORY 
; 安装过程页面 
!insertmacro MUI_PAGE_INSTFILES 
; 安装完成页面 

;在安装完成页面上显示要运行的程序。 
!define MUI_FINISHPAGE_RUN "$INSTDIR\spirit.exe" 
!insertmacro MUI_PAGE_FINISH 

; 安装卸载过程页面 
!insertmacro MUI_UNPAGE_INSTFILES 

; 安装界面包含的语言设置 
!insertmacro MUI_LANGUAGE "SimpChinese" 

; 安装预释放文件 
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS 
; ------ MUI 现代界面定义结束 ------ 

;安装程序的名字和版本号 
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" 
;编译后的安装程序的保存位置。 
OutFile "${PRODUCT_OUTDIR}\spirit_setup.exe" 
;安装路径 
InstallDir "$PROGRAMFILES\美剧精灵" 
;在安装过程中安装信息是否可见。(默认为可见,参数为hide只显示一个显示按钮，单击按钮还可以看到。) 
ShowInstDetails show 
ShowUnInstDetails show 

;安装程序下面线上的文字 
BrandingText "美剧精灵" 

;各个区段。 
;-----------------------主程序------------------------------------
Section "主程序" SEC01

;解压文件到安装目录
SetOutPath "$INSTDIR" 
SectionIn 1 2 3 RO 
SetOverwrite ifnewer 
File /r "${PRODUCT_OUTDIR}\bin\*.*" 

;写注册表安装信息
WriteRegStr HKLM "${PRODUCT_INST_VALUE_KEY}" "version" "${Version}"
WriteRegStr HKLM "${PRODUCT_INST_VALUE_KEY}" "InstallDir" "$INSTDIR"
WriteRegStr HKLM "${PRODUCT_INST_VALUE_KEY}" "channel" $SpiritChannel

;调用 dll获取 PeerID
StrCpy $PeerID "NoValue"
System::Call 'cutup::_getwpccode@4(i 0) t .r1'
StrCpy $PeerID $1
WriteRegStr HKLM "${PRODUCT_INST_VALUE_KEY}" "peerid" $PeerID

; 写注册表开机启动
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" "MJSpirit" "$INSTDIR\spirit.exe --minimize"

;在安装目录建立快捷方式
CreateShortCut "$INSTDIR\美剧精灵.lnk" "$INSTDIR\spirit.exe"

;上报安装统计
ExecShell "open" "$INSTDIR\stat.exe" "-type inst"


;在快速启动栏中创建快捷方式。 
CreateShortCut "$QUICKLAUNCH\美剧精灵.lnk" "$INSTDIR\spirit.exe" 

;创建开始菜单快捷方式
CreateDirectory "$SMPROGRAMS\美剧精灵" 
CreateShortCut "$SMPROGRAMS\美剧精灵\美剧精灵.lnk" "$INSTDIR\spirit.exe" 

WriteUninstaller "$INSTDIR\uninst.exe" 
CreateDirectory "$SMPROGRAMS\美剧精灵" 
CreateShortCut "$SMPROGRAMS\美剧精灵\卸载美剧精灵.lnk" "$INSTDIR\uninst.exe" 

SectionEnd 

;-----------------------是否开机启动--------------------------
Section "开机启动" runwithsys
SectionIn 1 2 3 

SectionEnd
;-----------------------创建桌面快捷方式--------------------------
Section "创建桌面快捷方式" desk 
SectionIn 1 2 3 
SetOverwrite ifnewer 
;在安装建立快捷方式。 
CreateShortCut "$DESKTOP\美剧精灵.lnk" "$INSTDIR\spirit.exe" 
SectionEnd 

;=========================卸载程序=================================
/****************************** 
* 以下是安装程序的卸载部分 * 
******************************/ 

;区段描述。 
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN 
!insertmacro MUI_DESCRIPTION_TEXT ${SEC01} "美剧精灵主程序,不可缺少的哦!" 
!insertmacro MUI_DESCRIPTION_TEXT ${desk} "创建桌面快捷方式!" 
!insertmacro MUI_DESCRIPTION_TEXT ${programlink} "创建开始菜单快捷方式!" 
!insertmacro MUI_DESCRIPTION_TEXT ${uninst} "创建卸载程序和[控制面板]的[添加或删除程序]中创建卸载程序图标!" 
!insertmacro MUI_FUNCTION_DESCRIPTION_END 

;以下是卸载区段。 
Section Uninstall 

/*
${if} $R0 >= 6.0
	ExecShell taskbarpin "$INSTDIR\美剧精灵.lnk"
${EndIF}
*/
	
#SetShellVarContext current
Delete "$DESKTOP\美剧精灵.lnk" 
SetShellVarContext all # 设置为所有用户才能删除下面的几个快捷方式
Delete "$QUICKLAUNCH\美剧精灵.lnk" 
Delete "$QUICKLAUNCH\卸载美剧精灵.lnk" 
#Delete "$SMPROGRAMS\美剧精灵\美剧精灵.lnk" 
#Delete "$SMPROGRAMS\美剧精灵\卸载美剧精灵.lnk" 
#Delete "$SMPROGRAMS\美剧精灵" 
RMDir /r "$SMPROGRAMS\美剧精灵" 

;上报卸载统计
ExecShell "open" "$INSTDIR\stat.exe" "-type uninst"
sleep 200

Delete "$INSTDIR\uninst.exe" 
RMDir /r "$INSTDIR" ; 有可能没完全删除， 例如 Stat.exe 在卸载时被调用，删除不了，需解决。

SetAutoClose true 
SectionEnd 

;安装时 初始化
Function .onInit

;获取安装包文件名
Call GetExeName
Pop $R2
StrCpy $InstFileName $R1

;从安装包文件名中读取渠道号
Call GetChannel
Pop $R0
${If} $R0 == NULL
	StrCpy $SpiritChannel "1"
${else}
	StrCpy $SpiritChannel $R0
${EndIf}

;检测是否正在运行spirit
Call CheckModule
FunctionEnd

#-- 根据 NSIS 脚本编辑规则，所有 Function 区段必须放置在 Section 区段之后编写，以避免安装程序出现未可预知的问题。--# 
;卸载时 初始化
Function un.onInit 
	Call un.CheckModule
MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "确定卸载美剧精灵吗?" IDYES +2 
Abort 
FunctionEnd 

Function un.onUninstSuccess
HideWindow 
MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) 已成功地从你的计算机移除。" 
FunctionEnd


#-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Function GetChannel
  ;文件名中 左起第一个下划线到右起第一个小数点之间的内容为 Channel 值
  StrCpy $R2 $EXEFILE
  
  StrLen $0 $R2 ; 文件名 长度
  StrCpy $1 $R2 ; 文件名 字符串
  StrCpy $2 0 ; 左起第一个下划线的位置
  StrCpy $3 $0 ; 右起第一个小数点的位置
  StrCpy $4 0 ; Channel 值

  ${Do}
    # 从左往右一直循环，找到第一个下划线为止
    StrCpy $R1 $1 1 $2 # 取一个字符
    ${If} $R1 == '_'
      ${ExitDo}
    ${EndIf}
    IntOp $2 $2 + 1
    ${If} $2 == $0
      # ${ExitDo}   ; 没有找到tn值
      # Code Goto return
      Goto tnNull
    ${EndIf}
  ${Loop}

  ${Do}
    # 从右往左一直循环，找到第一个小数点为止
    StrCpy $R1 $1 1 $3 # 取一个字符
    ${If} $R1 == '.'
      ${ExitDo}
    ${EndIf}
    IntOp $3 $3 - 1
    ${If} $3 == 0
      # ${ExitDo}   ; 没有找到tn值
      # Code Goto return
      Goto tnNull
    ${EndIf}
  ${Loop}

  IntOp $2 $2 + 1
  ${If} $3 == $2
    Goto tnNull
  ${EndIf}
  
  IntOp $5 $3 - $2
  StrCpy $4 $1 $5 $2
  Push $4

  ;Call GetTnLegal
  
  Goto tnEnd
tnNull:
  Push "NULL"
tnEnd:
FunctionEnd

Function GetExeName
  # $CMDLINE = "D:\WorkStation\wsmplayer\output\ni_hao\BaiduPlayer_aaa.exe"
  # 获取程序的文件名, 右边起第一个 "\" 之后的字符串
  System::Call 'kernel32::GetModuleFileName(i 0, t .R0, i 1024) i r1'

  StrLen $0 $R0 ; FullName 长度
  StrCpy $1 $R0 ; FullName 字符串
  StrCpy $2 $0 ; 右起第一个"\" 的位置

  ${Do}
    # 从右往左一直循环，找到第一个"\"为止
    StrCpy $R1 $1 1 $2
    ${If} $R1 == '\'
      ${ExitDo}
    ${EndIf}
    IntOp $2 $2 - 1
    ${If} $2 == 0
      ${ExitDo}  ; 没有找到 "\" 值
    ${EndIf}
  ${Loop}
  
  ${If} $2 == 0   ; 狗屎 不可能出现 ;没有找到字符"\", 如：BaiduPlayer_aa.exe，返回 整个$CMDLINE
    Push $CMDLINE
    Goto nameend
  ${EndIf}
  
  ${If} $2 == $0   ; 狗屎 不可能出现 ; 最后一个字符是\, 如：D:\WorkStation\wsmplayer\output\ni_hao\，返回NULL,
    Push "NULL"
    Goto nameend
  ${EndIf}
  
  IntOp $2 $2 + 1    ; "\" 的下一个位置,文件名得位置
  IntOp $3 $0 - $2   ; 文件名字的长度
  StrCpy $4 $1 $3 $2  ; 从$1的$2位置开始算起，取$3个字符, 存入$4
  Push $4 ; 文件名字 Software_aaa.exe
  #MessageBox MB_OK $CMDLINE
  #MessageBox MB_OK $4
nameend:

FunctionEnd


Var RegInsDir
;本函数检测spirit是否正在运行，并提示用户选择是否继续
!macro CheckModule PRE
Function ${PRE}CheckModule
;从注册表读上次的安装位置
ReadRegStr $RegInsDir HKLM "${PRODUCT_INST_VALUE_KEY}" "InstallDir"
${If} $RegInsDir == ""
	Return
${EndIf}

Module_check:
  nsSkinEngine::FindModuleInProcessByDirectoryAndKillProcess $RegInsDir "0" "1" "1" "0"
  Pop $0
  Pop $1
  ${If} $0 == "1"
	IntOp $1 $1 - 1
	Pop $3
	${While} $1 > 0
		IntOp $1 $1 - 1
		Pop $2
		StrCpy $3 "$3 $2"
	${EndWhile}
	
	MessageBox MB_OKCANCEL "$3程序正在运行！点“确定”结束进程并继续，“取消”退出。" IDOK OK IDCANCEL CANCEL
	OK:
		nsSkinEngine::FindModuleInProcessByDirectoryAndKillProcess $RegInsDir "1" "1" "0" "0"
		Pop $0
		sleep 200
		goto Module_check
	CANCEL:
	  Quit
  ${Else}
	Return
  ${EndIf}
FunctionEnd
!macroend

!insertmacro CheckModule ""
!insertmacro CheckModule "un."